﻿#region 命名空间

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using WinnerCMS.Common;
using WinnerCMS.CacheStorager;
using WinnerCMS.Model;
using WinnerCMS.BLL.CacheHepler;
using WinnerCMS.BLL.Rights;
using WinnerCMS.Model.Attribute;

#endregion

namespace WinnerCMS.BLL.Rights
{
    public class RightsControlManage
    {
        static RightsControlManage()
        {
            HuLue = new List<string>
            {
                "/login.aspx",
                "/err.aspx",
                "/logout.aspx",
                "/about.aspx",
                "/reg.aspx",
                "/getpassword.aspx"
            };
        }

        private readonly IList<Control> _uiControls;

        public RightsControlManage()
        {
            this._uiControls = new List<Control>();
        }

        #region 页面访问权限

        /// <summary>
        /// 页面访问权限
        /// </summary>
        /// <param name="content"></param>
        public static void CheckUrlAccess(HttpContext content)
        {
            PageMap[] pagerights = (from PageMap pm in SysRights.PageMaps
                                    where
                                        content.Request.Url.AbsolutePath.IndexOf(pm.AbsolutePath,
                                            StringComparison.CurrentCultureIgnoreCase) > -1
                                    select pm).ToArray();
            if (pagerights.Length < 1)
            {
                ErrClass.Redirect("你没有" + content.Request.Url.AbsolutePath + "页面的权限！");
            }
            else
            {
#if DEBUG
                if (pagerights.Length > 1)
                {
                    throw new InvalidDataException(pagerights[0].AbsolutePath + "配置重复");
                }
#endif
                if (!pagerights[0].Codes.Any() ||
                    pagerights[0].Codes[0].Length == 0)
                {
                    return;
                }
                string modelId = content.Request.QueryString["ModelId"];
                var c = (from string p in pagerights[0].Codes
                         join string r in RolePower
                             on (pagerights[0].IsMacthMID ? modelId : "") + p equals r
                         select p);
                if (c.Any() == false)
                {
                    ErrClass.Redirect("你没有" + content.Request.Url.AbsolutePath + "页面的权限！");
                }
            }
        }

        #endregion

        #region 查找所有控件

        /// <summary>
        /// 查找所有控件
        /// </summary>
        /// <param name="control"></param>
        /// <remarks>使用了递归算法，兼容任何层次的控件。</remarks>
        private void FindControls(Control control)
        {
            foreach (Control c in control.Controls)
            {
                if (c == null)
                    continue;
                if (c.ID == null)
                    continue;

                if (c is UpdatePanel)
                {
                    foreach (Control cc in (c as UpdatePanel).ContentTemplateContainer.Controls)
                    {
                        this._uiControls.Add(cc);
                        FindControls(cc);
                    }
                }
                //if (c is Button || c is ButtonX || c is CheckBox || c is GridView)
                {
                    this._uiControls.Add(c);
                }

                FindControls(c);
            }
        }

        #endregion

        #region 设置有权限的控件

        /// <summary>
        /// 设置有权限的控件
        /// </summary>
        /// <param name="page"></param>
        /// <remarks>现阶段只考虑 Button 控件</remarks>
        public void SetAllControl(Page page)
        {
            string pathAndQuery = page.Request.Url.PathAndQuery;
            string modelId = page.Request.QueryString["ModelId"];

            #region 禁用无权限控件

            //取出该页控件映射配置而且是没有权限的
            ControlMap[] cms = (from ControlMap r in SysRights.ControlMaps
                                where
                                    pathAndQuery.IndexOf(r.AbsolutePath, StringComparison.CurrentCultureIgnoreCase) > -1 &&
                                    !(from rp in RolePower select rp).Contains((r.IsMacthMID ? modelId : "") + r.Code)
                                select r).ToArray();

            FindControls(page);

            if (cms.Any() == false)
            {
                goto Label1;
            }

            List<string> controlIDs = new List<string>();
            foreach (var cm in cms)
            {
                controlIDs.AddRange(cm.Controls);
            }


            //无权限页面控件
            Control[] controls = (from Control c in this._uiControls
                                  where (from r in controlIDs
                                         select r).Contains(c.ID)
                                  select c).ToArray();
            //禁用无权限控件
            foreach (var c in controls)
            {
                if (c is Button)
                {
                    (c as Button).Enabled = false;
                }
                if (c is CheckBox)
                {
                    (c as CheckBox).Enabled = false;
                    (c as CheckBox).Checked = false;
                }
                else if (c is TextBox)
                {
                    (c as TextBox).Visible = false;
                }
                else
                {
                    (c as WebControl).Enabled = false;
                }
            }

            #endregion

            Label1:

            #region 禁用数据控件内无权限子控件

            //取出当前页的数据控件映射配置，而且是没有权限的
            List<DataControlMap> dcms = (from DataControlMap R in SysRights.DataControlMaps
                                         where
                                             pathAndQuery.IndexOf(R.AbsolutePath,
                                                 StringComparison.CurrentCultureIgnoreCase) > -1 &&
                                             !(from RA in RolePower select RA).Contains((R.IsMacthMID ? modelId : "") +
                                                                                        R.Code)
                                         select R).ToList();
            //含有
            controls = (from Control C in this._uiControls
                        where (from R in dcms
                               select R.Control).Contains(C.ID)
                        select C).ToArray();

            foreach (Control c in controls)
            {
                foreach (DataControlMap dcm in dcms.FindAll(dcm => dcm.Control == c.ID))
                    switch (c.GetType().Name)
                    {
                        case "GridView":
                            GridView GV = c as GridView;
                            foreach (GridViewRow row in GV.Rows)
                            {
                                Control CC = row.FindControl(dcm.ChildControl);
                                WebControlManage(CC, dcm.Message);
                            }
                            break;
                        case "Repeater":
                            Repeater RT = c as Repeater;
                            foreach (RepeaterItem item in RT.Items)
                            {
                                Control CC = item.FindControl(dcm.ChildControl);
                                WebControlManage(CC, dcm.Message);
                            }

                            break;
                        case "DataList":
                            DataList DL = c as DataList;
                            foreach (DataListItem item in DL.Items)
                            {
                                Control CC = item.FindControl(dcm.ChildControl);
                                WebControlManage(CC, dcm.Message);
                            }
                            break;
                    }
            }

            #endregion
        }

        private void WebControlManage(Control CC, string message)
        {
            if (CC is HyperLink)
            {
                (CC as HyperLink).Attributes.Add("onclick", string.Format("alert('{0}');return false;", message));
            }
            if (CC is ImageButton)
            {
                (CC as ImageButton).OnClientClick = string.Format("alert('{0}');return false;", message);
            }

            if (CC is LinkButton)
            {
                (CC as LinkButton).OnClientClick = string.Format("alert('{0}');return false;", message);
            }
            if (CC is Button)
            {
                (CC as Button).OnClientClick = string.Format("alert('{0}');return false;", message);
            }
        }

        #endregion

        #region 系统内置权限

        private static RightsMap _rightsMap;
        private static readonly object Lockhepler = new object();

        /// <summary>
        /// 系统内置权限
        /// </summary>
        private static RightsMap SysRights
        {
            get
            {
                if (_rightsMap == null)
                {
                    lock (Lockhepler)
                    {
                        if (_rightsMap == null)
                        {
                            //从配置文件读取
                            _rightsMap =
                                SerializableHelper.DeSerialize<RightsMap>(
                                    new FileInfo(HttpServer.MapPath("~/Admin/RightsMap.config")));

                            //用页面的特性读取
                            var adminWorkArea =
                                LoadAssemblyFromFile(HttpServer.MapPath("~/bin/WinnerCMS.WebUI.dll"))
                                    .GetTypes()
                                    .Where(x => x.FullName.StartsWith("WinnerCMS.WebUI.Admin"));
                            foreach (
                                var type in adminWorkArea.Where(x => x.GetCustomAttributes<AccessAttribute>(true).Any())
                                )
                            {
                                var absolutePath =
                                    type.FullName.Replace("WinnerCMS.WebUI.Admin.", "").Replace(".", "/") + ".aspx";
                                if (_rightsMap.PageMaps.Any(x => x.AbsolutePath == absolutePath))
                                {
                                    continue;
                                }

                                var access = type.GetCustomAttribute<AccessAttribute>(true);

                                _rightsMap.PageMaps.Add(new PageMap
                                {
                                    AbsolutePath = absolutePath,
                                    Codes = access.Codes
                                });
                            }

                            foreach (var pm in _rightsMap.PageMaps)
                            {
                                pm.AbsolutePath = WebConfig.BackGroundPath + pm.AbsolutePath;
                            }
                        }
                    }
                }
                return _rightsMap;
            }
        }

        #endregion

        #region 管理员权限

        /// <summary>
        /// 管理员权限
        /// </summary>
        private static IList<string> RolePower
        {
            get { return UserManage.Current.RightCodes; }
        }

        #endregion

        #region 不进行登录验证

        /// <summary>
        /// 不进行登录验证
        /// </summary>
        public static List<string> HuLue { get; private set; }

        #endregion

        public static Assembly LoadAssemblyFromFile(string fileFullName)
        {
            byte[] b = File.ReadAllBytes(fileFullName);
            Assembly asm = Assembly.Load(b);
            return asm;
        }
    }
}